import asyncio

import socketio
from typing import Any, Dict, List

from loguru import logger
from socketio import AsyncNamespace

from common.AesUtil import AesUtil
from service.ChattingMessageService import ChattingMessageService
from service.FriendsService import FriendService
from websocket.websocket_service import WebsocketService


class MyCustomNamespace(AsyncNamespace):


    def on_connect(self, sid, environ):
        # 获取查询参数
        query = environ["QUERY_STRING"]
        query_params = {}
        for i in query.split("&"):
            k, v = i.split("=")
            query_params[k] = v

        # 可以在这里执行其他操作，比如验证用户等

    def on_disconnect(self, sid):
        print(f"Client {sid} disconnected")

    async def on_message(self, sid, data):
        print(f"Received message: {data} from {sid}")
        await self.emit('response', {'status': 'Message received'}, room=sid)


# 注册命名空间

class EventsGateway:
    def __init__(self, sio: socketio.AsyncServer):
        self.sio = sio
        self.namespace = '/websocket'

        # 模拟 NestJS 的依赖注入
        self.chat_service = ChattingMessageService()
        self.friend_service = FriendService()
        self.websocket_service = WebsocketService(sio=self.sio)

        self.register_handlers()


    def register_handlers(self):

        @self.sio.on('connect', namespace=self.namespace)
        async def handle_connect(sid, environ):
            await self.handle_connection(sid, environ)

        @self.sio.on('disconnect', namespace=self.namespace)
        async def handle_disconnect(sid):
            print(f"Client {sid} disconnected")

        @self.sio.on('message', namespace=self.namespace)
        async def message(sid, data):
            try:
                data =  await self.send_message(sid,  data)
                logger.info(f"Sent message: {sid} {data}")
                # return data
                # await self.sio.emit('message', data, room=sid)
                return data
            except Exception as e:
                await self.emit_error(sid, "MessageError", str(e))
                raise e

        @self.sio.on('addFriend', namespace=self.namespace)
        async def handle_add_friend(sid, data):
            try:
                data = await self.add_friend(sid, data)
                return data
            except Exception as e:
                await self.emit_error(sid, "AddFriendError", str(e))
                raise e

        @self.sio.on('agreeFriend', namespace=self.namespace)
        async def handle_agree_friend(sid, data):
            try:
                data = await self.agree_friend(sid, data)
                return data
            except Exception as e:
                await self.emit_error(sid, "AgreeFriendError", str(e))

        @self.sio.on('joinChatingRoom', namespace=self.namespace)
        async def handle_join_room(sid, room_name: str):
            try:
                await self.join_chating_room(sid, room_name)
            except Exception as e:
                await self.emit_error(sid, "JoinRoomError", str(e))

        @self.sio.on('guest', namespace=self.namespace)
        async def handle_guest(sid):
            try:
                data = await self.guest_join_room(sid)
                return data
            except Exception as e:
                await self.emit_error(sid, "GuestError", str(e))

        @self.sio.on('getClientsInChatingRoom', namespace=self.namespace)
        async def handle_get_clients(sid, room_name: str):
            try:
                clients = await self.get_clients_in_room(room_name)
                return {
                    'room': room_name,
                    'clients': clients,
                    'count': len(clients)
                }
            except Exception as e:
                await self.emit_error(sid, "GetClientsError", str(e))

    async def handle_connection(self, sid, environ):
        query_string = environ.get("QUERY_STRING", "")
        client_ip = environ.get("REMOTE_ADDR", "")

        # 解析查询参数（例如 userId=xxx）
        from urllib.parse import parse_qs
        query_params = parse_qs(query_string)
        user_id = query_params.get("userId", [None])[0]

        if user_id:
            await self.websocket_service.update_socket_mes(sid, client_ip, user_id)
            await self.websocket_service.user_join_rooms(sid, user_id)

    async def send_message(self, sid, mes: Dict[str, Any]):
        return await self.chat_service.send_message(mes, sid, self.sio)

    async def add_friend(self, sid, mes: Dict[str, Any]):
        return await self.friend_service.add_friend(mes["fromUserId"], mes["targetUserName"])

    async def agree_friend(self, sid, mes: Dict[str, Any]):
        return await self.friend_service.agree_friend(sid, mes)

    async def join_chating_room(self, sid, room_name: str):
        return await self.websocket_service.join_chatting_room(sid, room_name)

    async def guest_join_room(self, sid):
        return await self.websocket_service.guest_join_room(sid)

    async def get_clients_in_room(self, room_name: str) -> List[str]:
        return list(self.sio.manager.rooms[self.namespace].get(room_name, {}).keys())

    async def emit_error(self, sid, error_type: str, message: str):
        asyncio.create_task(self.sio.emit('error', {'type': error_type, 'message': message}, room=sid, namespace=self.namespace))